home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 11: TSX-11 / Linux Cubed Series 11 - TSX-11 Vol 1.iso / sbin / bootutil.1 / bootutil / bootutils / mount / mount.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-01  |  10.6 KB  |  430 lines

  1. /*
  2.  * A mount(8) for Linux 0.97.
  3.  * $Header: /usr/src/mount/RCS/mount.c,v 1.1 1992/09/06 13:30:53 root Exp root $
  4.  */ 
  5.  
  6. #include "sundries.h"
  7.  
  8. #include <linux/fs.h>
  9.  
  10. const char *usage = "\
  11. Usage: mount [-anfrvw] [-t vfstypes]
  12.        mount [-nfrvw] special | node
  13.        mount [-nfrvw] [-t vfstype] [-o options] special node";
  14.  
  15. #ifdef notyet
  16. /* True for change options of an already mounted fs (-u).  */
  17. int update = 0;
  18. #endif
  19.  
  20. /* True for fake mount (-f).  */
  21. int fake = 0;
  22.  
  23. /* Don't write a entry in /etc/mtab */
  24. int nomtab = 0;
  25.  
  26. /* True for readonly (-r).  */
  27. int readonly = 0;
  28.  
  29. /* Nonzero for chatty (-v).  */
  30. int verbose = 0;
  31.  
  32. /* True for read/write (-w).  */
  33. int readwrite = 0;
  34.  
  35. /* True for all mount (-a).  */
  36. int all = 0;
  37.  
  38. /* Map from -o and fstab option strings to the flag argument to mount(2).  */
  39. struct opt_map
  40. {
  41.   const char *opt;        /* option name */
  42.   int  inv;            /* true if flag value should be inverted */
  43.   int  mask;            /* flag mask value */
  44. };
  45.  
  46. const struct opt_map opt_map[] =
  47. {
  48.   { "defaults",    0, 0        },    /* default options */
  49.   { "ro",    0, MS_RDONLY    },    /* read-only */
  50.   { "rw",    1, MS_RDONLY    },    /* read-write */
  51.   { "exec",    1, MS_NOEXEC    },    /* permit execution of binaries */
  52.   { "noexec",    0, MS_NOEXEC    },    /* don't execute binaries */
  53.   { "suid",    1, MS_NOSUID    },    /* honor suid executables */
  54.   { "nosuid",    0, MS_NOSUID    },    /* don't honor suid executables */
  55.   { "dev",    1, MS_NODEV    },    /* interpret device files  */
  56.   { "nodev",    0, MS_NODEV    },    /* don't interpret devices */
  57.   { "sync",    0, MS_SYNC    },    /* synchronous I/O */
  58.   { "async",    1, MS_SYNC    },    /* asynchronous I/O */
  59. #ifdef MS_NOSUB
  60.   { "sub",    1, MS_NOSUB    },    /* allow submounts */
  61.   { "nosub",    0, MS_NOSUB    },    /* don't allow submounts */
  62. #endif
  63.   /* add new options here */
  64. #ifdef MS_REMOUNT
  65.   { "remount",  0, MS_REMOUNT   },      /* Alter flags of mounted FS */
  66. #endif
  67.   { NULL,    0, 0        }
  68. };
  69.  
  70.  
  71. /* Report on a single mount.  */
  72. static void
  73. print_one (const struct mntent *mnt)
  74. {
  75.   printf ("%s on %s", mnt->mnt_fsname, mnt->mnt_dir);
  76.   if ((mnt->mnt_type != NULL) && *mnt->mnt_type != '\0')
  77.     printf (" type %s", mnt->mnt_type);
  78.   if (mnt->mnt_opts != NULL)
  79.     printf (" (%s)", mnt->mnt_opts);
  80.   printf ("\n");
  81. }
  82.  
  83. /* Report on everything in mtab (of the specified types if any).  */
  84. static volatile int
  85. print_all (string_list types)
  86. {
  87.   struct mntent *mnt;
  88.   
  89.   open_mtab ("r");
  90.  
  91.   while ((mnt = getmntent (F_mtab)) != NULL)
  92.     if (matching_type (mnt->mnt_type, types))
  93.       print_one (mnt);
  94.  
  95.   if (ferror (F_mtab))
  96.     die (1, "mount: error reading %s: %s", MOUNTED, strerror (errno));
  97.  
  98.   exit (0);
  99. }
  100.  
  101.  
  102. /* Look for OPT in opt_map table and return mask value.  If OPT isn't found,
  103.    tack it onto extra_opts.  Due to laziness, the first char of extra_opts
  104.    will be ',' if any extra options are found.  */
  105. static inline void
  106. parse_opt (const char *opt, int *mask, char *extra_opts)
  107. {
  108.   const struct opt_map *om;
  109.  
  110.   for (om = opt_map; om->opt != NULL; ++om)
  111.     if (streq (opt, om->opt))
  112.       {
  113.     if (om->inv)
  114.       *mask &= ~om->mask;
  115.     else
  116.       *mask |= om->mask;
  117.     return;
  118.       }
  119.   strcat (extra_opts, ",");
  120.   strcat (extra_opts, opt);
  121. }
  122.   
  123. /* Take -o options list and compute 4th and 5th args to mount(2).  flags
  124.    gets the standard options and extra_opts anything we don't recognize.  */
  125. static void
  126. parse_opts (char *opts, int *flags, char **extra_opts, int *noauto)
  127. {
  128.   char *opt;
  129.  
  130.   *noauto = 0;
  131.   if (opts != NULL)
  132.     {
  133.       *extra_opts = xmalloc (strlen (opts) + 1); 
  134.       **extra_opts = '\0';
  135.  
  136.       for (opt = strtok (opts, ",");
  137.        opt != NULL;
  138.        opt = strtok (NULL, ","))
  139.     if (streq (opt, "noauto"))
  140.       *noauto = 1;
  141.     else
  142.       parse_opt (opt, flags, *extra_opts);
  143.     }
  144.  
  145.   if (readonly)
  146.     *flags |= MS_RDONLY;
  147.   if (readwrite)
  148.     *flags &= ~MS_RDONLY;
  149. }
  150.  
  151. /* Fix opts_string to defaults if NULL, else merge readonly and readwrite.
  152.    Simplistic, merging ``-r'' with ``-o rw''a will give ``ro,rw''.  */
  153. static char *
  154. fix_opts_string (char *opts)
  155. {
  156.   char *fixed;
  157.  
  158.   if (readonly || readwrite)
  159.     {
  160.       if (opts == NULL)
  161.     return (readonly ? "ro" : "rw");
  162.  
  163.       fixed = xmalloc (strlen (opts) + 4);
  164.     
  165.       strcpy (fixed, readonly ? "ro," : "rw,");
  166.       strcat (fixed, opts);
  167.       return fixed;
  168.     }
  169.   return (opts == NULL ? "defaults" : opts);
  170. }
  171.  
  172. /* Mount a single file system.  Return status,
  173.    so don't exit on non-fatal errors.  */
  174. static int
  175. mount_one (char *spec, char *node, char *type, char *opts)
  176. {
  177.   struct mntent mnt = {0};
  178.   int mnt_err;
  179.   int flags = 0;
  180.   char *extra_opts = NULL;
  181.   int noauto = 0;
  182.  
  183.   if (opts && streq (opts, "defaults"))
  184.     opts = NULL;
  185.  
  186.   if (type == NULL)
  187.     {
  188.       if (strchr (spec, ':') != NULL)
  189.     type = "nfs";
  190.       else
  191.     type = FSTYPE_DEFAULT;
  192.     }
  193.  
  194.   parse_opts (xstrdup (opts), &flags, &extra_opts, &noauto);
  195.  
  196.   /* quietly succeed for fstab entries that don't get mounted automatically */
  197.   if (all && noauto)
  198.     return 0;
  199.  
  200.   if (!fake && streq (type, "nfs"))
  201. #ifdef HAVE_NFS
  202.     if (nfsmount (spec, node, &flags, &opts, &extra_opts) != 0)
  203.       return 1;
  204. #else
  205.     die (1, "mount: this version of mount doesn't support the type nfs");
  206. #endif
  207.  
  208.   block_signals (SIG_BLOCK);
  209.  
  210.   if (fake || (mount5 (spec, node, type, flags, extra_opts)) == 0)
  211.     /* Mount succeeded, write mtab entry.  */
  212.     {
  213.       if (!nomtab) {
  214.         mnt.mnt_fsname = canonicalize (spec);
  215.         mnt.mnt_dir = canonicalize (node);
  216.         mnt.mnt_type = type;
  217.         mnt.mnt_opts = fix_opts_string (opts);
  218.       
  219.         /* We get chatty now rather than after the update to mtab since the
  220.        mount succeeded, even if the write to /etc/mtab should fail.  */
  221.         if (verbose)
  222.         print_one (&mnt);
  223.  
  224.         if (!fake && (addmntent (F_mtab, &mnt)) == 1)
  225.         die (1, "mount: error writing %s: %s", MOUNTED, strerror (errno));
  226.       }
  227.  
  228.       block_signals (SIG_UNBLOCK);
  229.       return 0;
  230.     }
  231.     else
  232.       mnt_err = errno; /* work around for errno bug in sigprocmask */
  233.  
  234.   block_signals (SIG_UNBLOCK);
  235.  
  236.   /* Mount failed, complain, but don't die.  */
  237.   switch (mnt_err)
  238.     {
  239.     case EPERM:
  240.       if (geteuid() == 0)
  241.     error ("mount: mount point %s is not a directory", node);
  242.       else
  243.     error ("mount: must be superuser to use mount");
  244.       break;
  245.     case EBUSY:
  246.       error ("mount: wrong fs type, %s already mounted, %s busy, "
  247.     "or other error", spec, node);
  248.       break;
  249.     case ENOENT:
  250.       error ("mount: mount point %s does not exist", node); break;
  251.     case ENOTDIR:
  252.       error ("mount: mount point %s is not a directory", node); break;
  253.     case EINVAL:
  254.       error ("mount: %s not a mount point", spec); break;
  255.     case EMFILE:
  256.       error ("mount table full"); break;
  257.     case EIO:
  258.       error ("mount: %s: can't read superblock", spec); break;
  259.     case ENODEV:
  260.       error ("mount: fs type %s not supported by kernel", type); break;
  261.     case ENOTBLK:
  262.       error ("mount: %s is not a block device", spec); break;
  263.     case ENXIO:
  264.       error ("mount: %s is not a valid block device", spec); break;
  265.     case EACCES:
  266.       error ("mount: block device %s is not permitted on its filesystem", spec);
  267.       break;
  268.     default:
  269.       error ("mount: %s", strerror (mnt_err)); break;
  270.     }
  271.   return 1;
  272. }
  273.  
  274. /* Check if an fsname/dir pair was already in the old mtab.  */
  275. static int
  276. mounted (char *spec, char *node, string_list spec_list, string_list node_list)
  277. {
  278.   spec = canonicalize (spec);
  279.   node = canonicalize (node);
  280.  
  281.   while (spec_list != NULL)
  282.     {
  283.       if (streq (spec, car (spec_list)) && streq (node, car (node_list)))
  284.     return 1;
  285.       spec_list = cdr (spec_list);
  286.       node_list = cdr (node_list);
  287.     }
  288.     return 0;
  289. }
  290.  
  291. /* Mount all filesystems of the specified types except swap and root.  */
  292. static int
  293. mount_all (string_list types)
  294. {
  295.   struct mntent *fstab;
  296.   struct mntent *mnt;
  297.   string_list spec_list = NULL;
  298.   string_list node_list = NULL;
  299.   int status;
  300.  
  301.   open_mtab ("r");
  302.  
  303.   while ((mnt = getmntent (F_mtab)))
  304.     if (matching_type (mnt->mnt_type, types)
  305.     && !streq (mnt->mnt_dir, "/")
  306.     && !streq (mnt->mnt_dir, "root"))
  307.       {
  308.     spec_list = cons (xstrdup (mnt->mnt_fsname), spec_list);
  309.     node_list = cons (xstrdup (mnt->mnt_dir), node_list);
  310.       }
  311.  
  312.   close_mtab ();
  313.  
  314.   if (!nomtab) {
  315.     lock_mtab ();
  316.     open_mtab ("a+");
  317.     unlink (MOUNTED_LOCK);
  318.   }
  319.  
  320.   status = 0;
  321.   while ((fstab = getfsent ()) != NULL)
  322.     if (matching_type (fstab->mnt_type, types)
  323.      && !streq (fstab->mnt_dir, "/")
  324.      && !streq (fstab->mnt_dir, "root"))
  325.       if (mounted (fstab->mnt_fsname, fstab->mnt_dir, spec_list, node_list))
  326.     {
  327.       if (verbose)
  328.         printf("mount: %s already mounted on %s\n",
  329.            fstab->mnt_fsname, fstab->mnt_dir);
  330.     }
  331.       else
  332.         status |= mount_one (fstab->mnt_fsname,
  333.                  fstab->mnt_dir,
  334.                  fstab->mnt_type,
  335.                  fstab->mnt_opts);
  336.  
  337.   return status;
  338. }
  339.  
  340. int
  341. main (int argc, char **argv)
  342. {
  343.   int opt;
  344.   char *options = NULL;
  345.   string_list types = NULL;
  346.   struct mntent *fs;
  347.   char *spec;
  348.  
  349.   while ((opt = getopt (argc, argv, "naft:o:ruvw")) != EOF)
  350.     switch (opt)
  351.       {
  352.       case 'a':            /* mount everything in fstab */
  353.     ++all;
  354.     break;
  355.       case 'f':            /* fake (don't actually do mount(2) call) */
  356.     ++fake;
  357.     break;
  358.       case 't':            /* specify file system types */
  359.     types = parse_types (optarg);
  360.     break;
  361.       case 'o':            /* specify mount options */
  362.     options = optarg;
  363.     break;
  364.       case 'r':            /* mount readonly */
  365.     ++readonly;
  366.     break;
  367.       case 'n':            /* mount without writing in /etc/mtab */
  368.     ++nomtab;
  369.     break;
  370. #ifdef notyet
  371. /* Needs kernel support that we don't have yet, & some rewrites here also.  */
  372.       case 'u':            /* change options on an already mounted fs */
  373.     ++change; 
  374.     break;
  375. #endif
  376.       case 'v':            /* be chatty */
  377.     ++verbose;
  378.     break;
  379.       case 'w':            /* mount read/write */
  380.     ++readwrite;
  381.     break;
  382.       default:
  383.     die (2, usage);
  384.       }
  385.  
  386.   argc -= optind;
  387.   argv += optind;
  388.  
  389.   if (readonly && readwrite)
  390.     die (2, "mount: the -r and -w options conflict\n%s", usage);
  391.  
  392.   if (argc == 0)
  393.     if (options)
  394.       die (2, usage);
  395.     else if (all)
  396.       return mount_all (types);
  397.     else
  398.       return print_all (types);
  399.  
  400.   if (!nomtab) {
  401.     lock_mtab ();
  402.     open_mtab ("a+");
  403.     unlink (MOUNTED_LOCK);
  404.   }
  405.  
  406.   switch (argc)
  407.     {
  408.     case 1:
  409.       /* mount [-frvw] special | node */
  410.       if ((types != NULL) || (options != NULL))
  411.     die (2, usage);
  412.       /* Try to find the other pathname in fstab.  */ 
  413.       spec = canonicalize (*argv);
  414.       if (!(fs = getfsspec (spec)) && !(fs = getfsfile (spec)))
  415.     die (2, "mount: can't find %s in %s\n", spec, _PATH_FSTAB);
  416.       return mount_one (fs->mnt_fsname, fs->mnt_dir,
  417.             fs->mnt_type, fs->mnt_opts);
  418.     case 2:
  419.       /* mount [-frvw] [-t vfstype] [-o options] special node */
  420.       if (types == NULL)
  421.     return mount_one (argv[0], argv[1], NULL, options);
  422.       if (cdr (types) == NULL)
  423.     return mount_one (argv[0], argv[1], car (types), options);
  424.       die (2, usage);
  425.       
  426.     default:
  427.       die (2, usage);
  428.     }
  429. }
  430.